"""
Fact checking and verification system
"""
import logging
import re
from typing import List, Dict, Any, Optional, Tuple
from dataclasses import dataclass
from enum import Enum
from datetime import datetime, date

logger = logging.getLogger(__name__)

class FactType(Enum):
    """Types of facts that need checking"""
    NUMBER = "number"  # 数字
    DATE = "date"  # 日期
    QUOTE = "quote"  # 引用
    STATISTIC = "statistic"  # 统计数据
    CLAIM = "claim"  # 声明
    REFERENCE = "reference"  # 引用来源
    NAME = "name"  # 人名/地名/机构名

class VerificationStatus(Enum):
    """Verification status of facts"""
    VERIFIED = "verified"  # 已验证
    UNVERIFIED = "unverified"  # 未验证
    DISPUTED = "disputed"  # 有争议
    FALSE = "false"  # 错误
    PARTIALLY_TRUE = "partially_true"  # 部分正确

@dataclass
class FactItem:
    """Represents a fact that needs checking"""
    content: str
    fact_type: FactType
    context: str
    position: Tuple[int, int]  # Start and end position in text
    confidence_score: float
    verification_status: VerificationStatus = VerificationStatus.UNVERIFIED
    verification_source: Optional[str] = None
    verification_note: Optional[str] = None

@dataclass
class FactCheckResult:
    """Result of fact checking process"""
    original_text: str
    annotated_text: str
    facts: List[FactItem]
    credibility_score: float
    verification_suggestions: List[str]

class FactChecker:
    """System for fact checking and verification"""
    
    def __init__(self):
        """Initialize fact checker"""
        self.patterns = self._init_patterns()
        self.verification_apis = {}  # Placeholder for third-party APIs
        
    def _init_patterns(self) -> Dict[FactType, List[re.Pattern]]:
        """Initialize regex patterns for fact extraction"""
        return {
            FactType.NUMBER: [
                re.compile(r'\d+\.?\d*\s*[%％]'),  # Percentages
                re.compile(r'[￥$]\s*\d+(?:\.\d+)?(?:[万亿]|万亿)?'),  # Currency
                re.compile(r'\d+(?:\.\d+)?\s*(?:万|亿|千万|百万)'),  # Large numbers (Chinese)
                re.compile(r'\d+(?:,\d{3})*(?:\.\d+)?'),  # Formatted numbers
            ],
            FactType.DATE: [
                re.compile(r'\d{4}年\d{1,2}月\d{1,2}日'),  # Chinese date
                re.compile(r'\d{4}-\d{1,2}-\d{1,2}'),  # ISO date
                re.compile(r'\d{1,2}月\d{1,2}日'),  # Month-day
                re.compile(r'(?:今年|去年|前年|明年)'),  # Relative dates
            ],
            FactType.QUOTE: [
                re.compile(r'"([^"]+)"'),  # Quoted text
                re.compile(r'"([^"]+)"'),  # Chinese quotes
                re.compile(r'「([^」]+)」'),  # Japanese-style quotes
            ],
            FactType.STATISTIC: [
                re.compile(r'(?:增长|下降|上升|减少)\s*\d+\.?\d*\s*[%％]'),
                re.compile(r'(?:同比|环比)\s*\d+\.?\d*\s*[%％]'),
                re.compile(r'第[一二三四五六七八九十\d]+(?:位|名|大)'),
            ],
            FactType.REFERENCE: [
                re.compile(r'(?:根据|据|按照|参考)\s*([^，。]+?)(?:显示|表明|指出|称)'),
                re.compile(r'([^，。]+?)(?:报道|报告|发布|公布)'),
            ],
            FactType.NAME: [
                re.compile(r'(?:公司|集团|机构|组织|部门|委员会)'),
                re.compile(r'[A-Z][a-z]+(?:\s+[A-Z][a-z]+)*'),  # English names
            ]
        }
    
    def check_facts(
        self,
        text: str,
        context: Optional[Dict[str, Any]] = None
    ) -> FactCheckResult:
        """
        Main fact checking method
        
        Args:
            text: Text to check
            context: Additional context for verification
            
        Returns:
            Fact checking result
        """
        # Extract facts from text
        facts = self.extract_facts(text)
        
        # Mark facts for verification
        facts = self.mark_verification_needed(facts)
        
        # Generate annotated text
        annotated_text = self.annotate_text(text, facts)
        
        # Calculate overall credibility score
        credibility_score = self.calculate_credibility_score(facts)
        
        # Generate verification suggestions
        suggestions = self.generate_verification_suggestions(facts)
        
        return FactCheckResult(
            original_text=text,
            annotated_text=annotated_text,
            facts=facts,
            credibility_score=credibility_score,
            verification_suggestions=suggestions
        )
    
    def extract_facts(self, text: str) -> List[FactItem]:
        """
        Extract facts from text
        
        Args:
            text: Text to analyze
            
        Returns:
            List of extracted facts
        """
        facts = []
        
        for fact_type, patterns in self.patterns.items():
            for pattern in patterns:
                for match in pattern.finditer(text):
                    # Get surrounding context
                    start = max(0, match.start() - 50)
                    end = min(len(text), match.end() + 50)
                    context = text[start:end]
                    
                    fact = FactItem(
                        content=match.group(),
                        fact_type=fact_type,
                        context=context,
                        position=(match.start(), match.end()),
                        confidence_score=self._assess_confidence(
                            match.group(),
                            fact_type,
                            context
                        )
                    )
                    
                    facts.append(fact)
        
        # Remove duplicate facts
        facts = self._deduplicate_facts(facts)
        
        return facts
    
    def _assess_confidence(
        self,
        content: str,
        fact_type: FactType,
        context: str
    ) -> float:
        """Assess confidence in extracted fact"""
        confidence = 0.5  # Base confidence
        
        # Adjust based on fact type
        if fact_type in [FactType.NUMBER, FactType.DATE]:
            confidence = 0.7
        elif fact_type == FactType.STATISTIC:
            confidence = 0.6
        elif fact_type == FactType.QUOTE:
            confidence = 0.8
        
        # Check for hedging language
        hedging_words = ["可能", "大约", "约", "左右", "据说", "传闻", "疑似"]
        if any(word in context for word in hedging_words):
            confidence -= 0.2
        
        # Check for certainty markers
        certainty_words = ["确认", "证实", "官方", "正式", "准确"]
        if any(word in context for word in certainty_words):
            confidence += 0.1
        
        return min(max(confidence, 0), 1)
    
    def _deduplicate_facts(self, facts: List[FactItem]) -> List[FactItem]:
        """Remove duplicate facts"""
        seen = set()
        unique_facts = []
        
        for fact in facts:
            # Create unique key
            key = (fact.content, fact.fact_type, fact.position[0])
            
            if key not in seen:
                seen.add(key)
                unique_facts.append(fact)
        
        return unique_facts
    
    def mark_verification_needed(
        self,
        facts: List[FactItem]
    ) -> List[FactItem]:
        """
        Mark which facts need verification
        
        Args:
            facts: List of facts
            
        Returns:
            Facts with verification markers
        """
        for fact in facts:
            # High priority verification
            if fact.fact_type in [FactType.STATISTIC, FactType.CLAIM]:
                fact.verification_status = VerificationStatus.UNVERIFIED
                fact.verification_note = "需要验证统计数据准确性"
                
            # Numbers and dates
            elif fact.fact_type in [FactType.NUMBER, FactType.DATE]:
                if fact.confidence_score < 0.7:
                    fact.verification_status = VerificationStatus.UNVERIFIED
                    fact.verification_note = "建议核实数字/日期"
                    
            # Quotes
            elif fact.fact_type == FactType.QUOTE:
                fact.verification_status = VerificationStatus.UNVERIFIED
                fact.verification_note = "需要确认引用来源"
                
            # Low confidence items
            elif fact.confidence_score < 0.5:
                fact.verification_status = VerificationStatus.UNVERIFIED
                fact.verification_note = "可信度较低，建议验证"
        
        return facts
    
    def annotate_text(
        self,
        text: str,
        facts: List[FactItem]
    ) -> str:
        """
        Add annotations to text for facts needing verification
        
        Args:
            text: Original text
            facts: List of facts
            
        Returns:
            Annotated text
        """
        # Sort facts by position (reverse order to maintain positions)
        sorted_facts = sorted(facts, key=lambda f: f.position[0], reverse=True)
        
        annotated = text
        
        for fact in sorted_facts:
            if fact.verification_status == VerificationStatus.UNVERIFIED:
                # Create annotation
                annotation = self._create_annotation(fact)
                
                # Insert annotation
                start, end = fact.position
                annotated = (
                    annotated[:start] +
                    f"[{fact.content}]^({annotation})" +
                    annotated[end:]
                )
        
        return annotated
    
    def _create_annotation(self, fact: FactItem) -> str:
        """Create annotation text for a fact"""
        type_labels = {
            FactType.NUMBER: "数字",
            FactType.DATE: "日期",
            FactType.QUOTE: "引用",
            FactType.STATISTIC: "统计",
            FactType.CLAIM: "声明",
            FactType.REFERENCE: "来源",
            FactType.NAME: "名称"
        }
        
        label = type_labels.get(fact.fact_type, "事实")
        
        if fact.verification_note:
            return f"{label}: {fact.verification_note}"
        else:
            return f"{label}: 需要验证"
    
    def calculate_credibility_score(
        self,
        facts: List[FactItem]
    ) -> float:
        """
        Calculate overall credibility score
        
        Args:
            facts: List of facts
            
        Returns:
            Credibility score (0-1)
        """
        if not facts:
            return 0.8  # Default for text without specific facts
        
        # Calculate weighted average of confidence scores
        total_weight = 0
        weighted_sum = 0
        
        # Weights for different fact types
        type_weights = {
            FactType.STATISTIC: 2.0,
            FactType.NUMBER: 1.5,
            FactType.QUOTE: 1.5,
            FactType.DATE: 1.0,
            FactType.CLAIM: 2.0,
            FactType.REFERENCE: 1.0,
            FactType.NAME: 0.5
        }
        
        for fact in facts:
            weight = type_weights.get(fact.fact_type, 1.0)
            
            # Adjust score based on verification status
            score = fact.confidence_score
            if fact.verification_status == VerificationStatus.VERIFIED:
                score = 1.0
            elif fact.verification_status == VerificationStatus.FALSE:
                score = 0.0
            elif fact.verification_status == VerificationStatus.DISPUTED:
                score = 0.5
            
            weighted_sum += score * weight
            total_weight += weight
        
        if total_weight > 0:
            credibility = weighted_sum / total_weight
        else:
            credibility = 0.5
        
        return min(max(credibility, 0), 1)
    
    def generate_verification_suggestions(
        self,
        facts: List[FactItem]
    ) -> List[str]:
        """
        Generate suggestions for fact verification
        
        Args:
            facts: List of facts
            
        Returns:
            List of verification suggestions
        """
        suggestions = []
        
        # Group facts by type
        facts_by_type = {}
        for fact in facts:
            if fact.verification_status == VerificationStatus.UNVERIFIED:
                if fact.fact_type not in facts_by_type:
                    facts_by_type[fact.fact_type] = []
                facts_by_type[fact.fact_type].append(fact)
        
        # Generate suggestions by type
        if FactType.STATISTIC in facts_by_type:
            count = len(facts_by_type[FactType.STATISTIC])
            suggestions.append(f"验证{count}个统计数据的来源和准确性")
        
        if FactType.QUOTE in facts_by_type:
            count = len(facts_by_type[FactType.QUOTE])
            suggestions.append(f"确认{count}处引用的原始出处")
        
        if FactType.NUMBER in facts_by_type:
            count = len(facts_by_type[FactType.NUMBER])
            suggestions.append(f"核实{count}个数字的准确性")
        
        if FactType.DATE in facts_by_type:
            count = len(facts_by_type[FactType.DATE])
            suggestions.append(f"确认{count}个日期的正确性")
        
        if FactType.CLAIM in facts_by_type:
            suggestions.append("验证关键声明的真实性")
        
        # Add general suggestions
        if len(facts) > 5:
            suggestions.append("建议对关键事实进行交叉验证")
        
        if any(f.confidence_score < 0.5 for f in facts):
            suggestions.append("部分内容可信度较低，需要额外验证")
        
        return suggestions
    
    async def verify_with_api(
        self,
        fact: FactItem,
        api_name: str = "default"
    ) -> FactItem:
        """
        Verify fact using external API (placeholder)
        
        Args:
            fact: Fact to verify
            api_name: Name of verification API
            
        Returns:
            Updated fact with verification result
        """
        # Placeholder for API integration
        # In production, this would call actual fact-checking APIs
        
        logger.info(f"API verification placeholder for: {fact.content}")
        
        # Simulate verification
        fact.verification_status = VerificationStatus.UNVERIFIED
        fact.verification_source = f"{api_name}_api"
        fact.verification_note = "外部API验证接口预留"
        
        return fact
    
    def generate_fact_report(
        self,
        result: FactCheckResult
    ) -> str:
        """
        Generate a readable fact-checking report
        
        Args:
            result: Fact checking result
            
        Returns:
            Formatted report
        """
        report_parts = []
        
        # Header
        report_parts.append("【事实核查报告】\n")
        
        # Overall credibility
        credibility_pct = result.credibility_score * 100
        report_parts.append(f"整体可信度: {credibility_pct:.1f}%\n")
        
        # Facts summary
        total_facts = len(result.facts)
        unverified = sum(
            1 for f in result.facts
            if f.verification_status == VerificationStatus.UNVERIFIED
        )
        
        report_parts.append(f"识别事实: {total_facts}个")
        report_parts.append(f"待验证: {unverified}个\n")
        
        # Facts by type
        if result.facts:
            report_parts.append("事实类型分布:")
            
            type_counts = {}
            for fact in result.facts:
                type_name = fact.fact_type.value
                type_counts[type_name] = type_counts.get(type_name, 0) + 1
            
            for type_name, count in type_counts.items():
                report_parts.append(f"  - {type_name}: {count}个")
        
        # Verification suggestions
        if result.verification_suggestions:
            report_parts.append("\n建议验证:")
            for suggestion in result.verification_suggestions:
                report_parts.append(f"  • {suggestion}")
        
        # High-priority facts
        high_priority = [
            f for f in result.facts
            if f.confidence_score < 0.5 and
            f.verification_status == VerificationStatus.UNVERIFIED
        ]
        
        if high_priority:
            report_parts.append("\n高优先级验证项:")
            for fact in high_priority[:5]:
                report_parts.append(f"  - {fact.content} ({fact.fact_type.value})")
        
        return "\n".join(report_parts)